#ifndef GTL_ENGINE_GAME_OBJECT_HEADER_GUARD
#define GTL_ENGINE_GAME_OBJECT_HEADER_GUARD

#include "gtlState.h"
#include "gtlEvent.h"
#include "gtlCore.h"
#include "gtlProperty.h"

namespace GTL { namespace Engine {

	template <>
	inline GameEvent* GetCast<GameEvent*>(const GTL::Functions::VariableVariant& var)
	{
		return (GameEvent*)(void*)var;
	}

	using namespace GTL::AutoMembers;

	class GameObject : public Producible
	{
	public:
		static GameObject* ProduceFromFile( const char* filename );

		State* GetState(const char* name);

		int CallEventVarArgs(const char* name, const GTL::Functions::VariableVariant* args, size_t argc, Event::EventHandler* handler = 0);

		int CallEvent(const char* name);
		template <typename A1>
		int CallEvent(const char* name, A1 a1) {
			GTL::Functions::VariableVariant arg = a1;
			return CallEventVarArgs(name, &arg, 1);
		}
		template <typename A1, typename A2>
		int CallEvent(const char* name, A1 a1, A2 a2) {
			GTL::Functions::VariableVariant args[2] = { a1, a2 };
			return CallEventVarArgs(name, args, 2);
		}

		void SwitchIntoState(const char* state);
		void SwitchIntoState(StateHolder& state);
		void SwitchToParentState();
		bool IsInState(const char* state) const { return mCurrentState && !strcmp(mCurrentState->StateName, state); }
		bool IsInState(StateHolder& state) const { return mCurrentState == &state; }

		int OnUpdate(float dt);
		int OnDraw(float dt);
		int OnEvent(GameEvent ev);

		property (float, TimeDilation, 1.0f);
	protected:
		StateHolder* mCurrentState;
		StateHolder* mNextState;
		virtual int OnDestroy()
		{
			return 0;
		}
	private:
		void SwitchState( StateHolder* i );

		virtual int OnCreate()
		{
			/// TODO: Do error checking (make sure properties are not in states, etc.)

			/// find first state on list and activate it
			for (AutoMember* i=mMembers; i; i = i->Next)
			{
				if (i->GetType() == 'stat')
				{
					mNextState = mCurrentState = (StateHolder*)i;
					break;
				}
			}
			
			if (mCurrentState)
			{
				Event::EventHandler* switchEvent = mCurrentState->GetEvent("Enter", true);
				if (switchEvent)
					Event::CallEvent(switchEvent, 0, 0);
			}
			return 0;
		}

		Event::EventHandler* GetEventHandler(const char* name);
	};
}}

#endif // gtlGameObject_h__